<!--
 * @Descripttion: 文件导出
 * @version: 1.1
 * @Author: sakuya
 * @Date: 2022年5月24日16:20:12
 * @LastEditors: sakuya
 * @LastEditTime: 2022年6月13日17:32:05
-->

<template>
  <slot :open="open">
    <el-button type="primary" plain @click="open">导出</el-button>
  </slot>
  <el-drawer v-model="dialog" title="导出" :size="400" direction="rtl" append-to-body destroy-on-close>
    <el-main style="padding: 0 20px 20px 20px">
      <div v-loading="downLoading" element-loading-text="正在处理中...">
        <div v-if="downLoading && progress" style="
            position: absolute;
            width: 100%;
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 3000;
          ">
          <el-progress :text-inside="true" :stroke-width="20" :percentage="downLoadProgress"
            style="width: 100%; margin-bottom: 120px" />
        </div>
        <el-tabs>
          <el-tab-pane label="常规" lazy>
            <el-form label-width="100px" label-position="left" style="margin: 10px 0 20px 0">
              <el-form-item label="文件名">
                <el-input v-model="formData.fileName" placeholder="请输入文件名" />
              </el-form-item>
              <el-form-item label="文件类型">
                <el-select v-model="formData.fileType" placeholder="请选择文件类型">
                  <el-option v-for="item in fileTypes" :key="item" :label="'*.' + item" :value="item" />
                </el-select>
              </el-form-item>
              <slot name="form" :form-data="formData"></slot>
            </el-form>
            <el-button v-if="async" type="primary" size="large" icon="el-icon-plus" style="width: 100%"
              :loading="asyncLoading" @click="download">发起导出任务</el-button>
            <el-button v-else type="primary" size="large" icon="el-icon-download" style="width: 100%"
              @click="download">下 载</el-button>
          </el-tab-pane>
          <el-tab-pane v-if="columnData.length > 0" label="列设置" lazy>
            <columnSet :column="columnData"></columnSet>
          </el-tab-pane>
          <el-tab-pane v-if="data && showData" label="其他参数" lazy>
            <el-descriptions :column="1" border size="small">
              <el-descriptions-item v-for="(val, key) in data" :key="key" :label="key">{{
                val
                }}</el-descriptions-item>
            </el-descriptions>
          </el-tab-pane>
        </el-tabs>
      </div>
    </el-main>
  </el-drawer>
</template>

<script>
import columnSet from './column'

export default {
  components: {
    columnSet
  },
  props: {
    apiObj: { type: Object, default: () => { } },
    fileName: { type: String, default: '' },
    fileTypes: { type: Array, default: () => ['xlsx'] },
    data: { type: Object, default: () => { } },
    showData: { type: Boolean, default: false },
    async: { type: Boolean, default: false },
    column: { type: Array, default: () => [] },
    blob: { type: Boolean, default: false },
    progress: { type: Boolean, default: true }
  },
  data() {
    return {
      dialog: false,
      formData: {
        fileName: this.fileName,
        fileType: this.fileTypes[0]
      },
      columnData: [],
      downLoading: false,
      downLoadProgress: 0,
      asyncLoading: false
    }
  },
  watch: {
    'formData.fileType'(val) {
      if (this.formData.fileName.includes('.')) {
        this.formData.fileName =
          this.formData.fileName.substring(0, this.formData.fileName.lastIndexOf('.')) + '.' + val
      } else {
        this.formData.fileName = this.formData.fileName + '.' + val
      }
    }
  },
  mounted() { },
  methods: {
    open() {
      this.dialog = true
      this.formData = {
        fileName:
          (this.fileName ? this.fileName : new Date().getTime() + '') + '.' + this.fileTypes[0],
        fileType: this.fileTypes[0]
      }
      this.columnData = JSON.parse(JSON.stringify(this.column))
    },
    close() {
      this.dialog = false
    },
    download() {
      let columnArr = {
        column: this.columnData
          .filter((n) => !n.hide)
          .map((n) => n.prop)
          .join(',')
      }
      let assignData = { ...this.data, ...this.formData, ...columnArr }
      if (this.async) {
        this.asyncDownload(this.apiObj, this.formData.fileName, assignData)
      } else if (this.blob) {
        this.downloadFile(this.apiObj, this.formData.fileName, assignData)
      } else {
        this.linkFile(this.apiObj.url, this.formData.fileName, assignData)
      }
    },
    linkFile(url, fileName, data = {}) {
      let a = document.createElement('a')
      a.style = 'display: none'
      a.target = '_blank'
      //a.download = fileName
      a.href = url + this.toQueryString(data)
      document.body.appendChild(a)
      a.click()
      document.body.removeChild(a)
    },
    downloadFile(apiObj, fileName, data = {}) {
      this.downLoading = true
      var _this = this
      apiObj
        .get(data, {
          responseType: 'blob',
          onDownloadProgress(e) {
            if (e.lengthComputable) {
              _this.downLoadProgress = parseInt((e.loaded / e.total) * 100)
            }
          }
        })
        .then((res) => {
          this.downLoading = false
          this.downLoadProgress = 0
          let url = URL.createObjectURL(res)
          let a = document.createElement('a')
          a.style = 'display: none'
          a.target = '_blank'
          a.download = fileName
          a.href = url
          document.body.appendChild(a)
          a.click()
          document.body.removeChild(a)
          URL.revokeObjectURL(url)
        })
        .catch((err) => {
          this.downLoading = false
          this.downLoadProgress = 0
          this.$notify.error({
            title: '下载文件失败',
            message: err
          })
        })
    },
    asyncDownload(apiObj, fileName, data = {}) {
      this.asyncLoading = true
      apiObj
        .get(data)
        .then((res) => {
          this.asyncLoading = false
          if (res.code == 200) {
            this.dialog = false
            this.$msgbox({
              title: '成功发起任务',
              message: `<div><img style="height:200px" src="/img/tasks-example.png"/></div><p>已成功发起导出任务，您可以操作其他事务</p><p>稍后可在 <b>任务中心</b> 查看执行结果</p>`,
              type: 'success',
              confirmButtonText: '知道了',
              dangerouslyUseHTMLString: true,
              center: true
            }).catch(() => { })
          } else {
            this.$alert(res.message || '未知错误', '发起任务失败', {
              type: 'error',
              center: true
            }).catch(() => { })
          }
        })
        .catch(() => {
          this.asyncLoading = false
        })
    },
    toQueryString(obj) {
      let arr = []
      for (var k in obj) {
        arr.push(`${k}=${obj[k]}`)
      }
      return (arr.length > 0 ? '?' : '') + arr.join('&')
    }
  }
}
</script>

<style></style>
